#include <iostream>
#include <string>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#include "anonymous_ftp_login.h"
#include "lib/lib_for_lua.h"
#include "lib/lib_for_python.h"

using namespace std;

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

#define MAX_LEN 256

xmlNodeSetPtr getNodes(xmlXPathContextPtr context, xmlXPathObjectPtr result, const xmlChar *xpath)
{
    result = xmlXPathEvalExpression(xpath, context);
    if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
        xmlXPathFreeObject(result);
        cout << "result is empty " << endl;
        return NULL;
    } else {
        return result->nodesetval;
    }
}

int runLua(xmlXPathContextPtr context, xmlXPathObjectPtr result)
{
    DIR		        *dp;
    struct dirent   *dir;
    xmlNodePtr      cur;
    xmlNodeSetPtr   nodes = NULL;
    xmlChar         *url;
    char            exec_file[MAX_LEN];

    lua_State	*L = lua_open();
    luaL_openlibs(L);
    //Try luaopen_package. If you want to open all standard Lua libraries,call luaL_openlibs.
    //luaopen_package(L);
    //遍历lua目录下的脚本
    dp		   = opendir("lua/");
    if (!dp) {
        cout << "opendir err" << endl;
    } else {
        while (dir = readdir(dp)) {
            if (dir->d_type & DT_DIR) {
                continue;
            }
            //查找相应脚本的配置参数
            nodes = getNodes(context, result, (const xmlChar *)(string("//lua[@type='")+string(dir->d_name)+string("']/target")).c_str());
            if (nodes == NULL) {
                return 1;
            } 
            int size = nodes->nodeNr;
            for (int i = 0; i < size; i++) {
                if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
                    cur = nodes->nodeTab[i];
                    url = xmlNodeGetContent(cur);
                    cout << url << " : " << endl;
                    memset(exec_file, 0, sizeof(exec_file));
                    strcpy(exec_file, "lua/");

                    strcat(exec_file, dir->d_name);
                    cout << exec_file << endl;
                    luaL_dofile(L, exec_file);
                    lua_http_version_detect(L, (char *)url);

                    xmlFree(url);
                }
            }
        }
        closedir(dp);
    }
    lua_close(L);
    return 0;
}

int runPython(xmlXPathContextPtr context, xmlXPathObjectPtr result)
{
    xmlNodePtr      cur;
    xmlNodeSetPtr   nodes = NULL;
    DIR		        *dp;
    struct dirent   *dir;
    xmlChar         *args;
    int             i;
    PyObject *pName = NULL, *pModule = NULL, *pDict = NULL, *pFunc = NULL;
    char            file_name[MAX_LEN];

    Py_Initialize();

    if (!Py_IsInitialized()) {
        cout << "python initialize error" << endl;
        return -1;
    }
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('/home/xudong/myproject/viruscan/src/python/')");

    dp = opendir("python/");
    if (!dp) {
        cout << "open python dir err" << endl;
    } else {
        while (dir = readdir(dp)) {
            if (dir->d_type & DT_DIR) {
                continue;
            }
            //查找相应脚本的配置参数
            nodes = getNodes(context, result, (const xmlChar *)(string("//python[@type='")+string(dir->d_name)+string("']/target")).c_str());
            if (nodes == NULL) {
                //return 1;
                continue;
            } 
            
            //去除文件名称后面的.py
            for (i=0; i< strlen(dir->d_name); i++) {
                if (dir->d_name[i] == '.') {
                    memcpy(file_name, dir->d_name, i);
                    break;
                }
            }
            file_name[i] = '\0';

            pName = PyString_FromString(file_name);
            pModule = PyImport_Import(pName);
            if (!pModule) {
                cout << "cann't find " << dir->d_name << endl;
                return -1;
            }
            pDict = PyModule_GetDict(pModule);
            if (!pDict) {
                cout << "pDict is error" << endl;
                return -1;
            }

            pFunc = PyDict_GetItemString(pDict, "main");
            if (!pFunc || !PyCallable_Check(pFunc)) {
                cout << "can't find function [main]" << endl;
                return -1;
            }

            int size = nodes->nodeNr;
            for (int i = 0; i < size; i++) {
                if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
                    cur = nodes->nodeTab[i];
                    args = xmlNodeGetContent(cur);
#if DEBUG
                    cout << args << " : " << endl;
#endif

                    python_func_add((char *)args, pFunc);

                    xmlFree(args);
                }
            }


        }
        closedir(dp);
    }
    Py_DECREF(pFunc);
    Py_DECREF(pDict);
    Py_DECREF(pModule);
    Py_DECREF(pName);

    Py_Finalize();
    return 0;
}

int main(int argc, char **argv)
{
    xmlDocPtr	        doc;
    xmlXPathContextPtr  context = NULL;
    xmlXPathObjectPtr   result = NULL;

    if (argc != 2) {
        cout << "参数不对！" << endl;
        usage();
        return -1;
    }
    //获得配置文件
    string	 file_path   = "tasks/" + string(argv[1]) + "/config.xml";
    doc = xmlReadFile(file_path.c_str(), NULL, 0);
    if (doc == NULL ) {
        cout << "open config file error " << endl;
        return 1;
    }
    context = xmlXPathNewContext(doc);
    // lua 插件调用
    // http_version_detect 插件调用
    runLua(context, result);
    // python 插件调用
    runPython(context, result);

    //  action(argc, argv);
    xmlXPathFreeContext(context);
    if (result) {
        xmlXPathFreeObject(result);
    }
    xmlFreeDoc(doc);
    xmlCleanupParser();
    return 0;
}

